#ifndef __L610_H
#define __L610_H


#ifdef __cplusplus
extern "C" {
#endif 

#include "gd32e10x.h"
#include "globalDef.h"


#define MAX_RECV_L610_IRT_LEN	1800		//用于中断接收最大长度判断

#define MAX_RECV_L610_LEN	1500				//一条协议最大长度
#define MAX_SEND_L610_LEN	1500       //发数据的协议最大长度                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       

//超时收不到L610内容则重启L610，暂定10分钟，后期根据需要可调整为3分钟
#define def_maxRebootL610Sec 600

typedef struct
{
	
	uint8_t rxDlyMaxSec;		//中断收取一组报文的最大延时，暂定2秒，超时清接收标记
	

	
	//用于7E协议解析
	uint8_t deal_sta;
	uint8_t deal_buf[MAX_RECV_L610_LEN];
	uint16_t deal_index;
	
	

	uint8_t rxDlyMaxSec2;			//中断收取一组报文的最大延时，暂定2秒，超时清接收标记
	
	//用于7E协议解析
	uint8_t deal_sta2;
	uint8_t deal_buf2[MAX_RECV_L610_LEN];
	uint16_t deal_index2;


	
	
	//心跳和重启相关变量
	uint16_t heatBeatDlySec;
	uint16_t rebootL610DlySec;			//超过某一数值，则重启L610 #define def_maxRebootL610Sec 600
	uint8_t rebootStep;					//重启L610步骤，先断电3秒等待释放电荷，再上电。
	
	
	uint8_t activePushMsgSta;			//1时主动上报
	
	uint8_t OnlyL610GeneralAnswer;		//1代表收到的L610通用应答,0代表收到的其它内容，可能需要主程序处理一圈
	uint8_t restartCANHardware;			//1时重启CAN硬件

	//继电器供断电
	uint8_t relayPowerCtrl;				//1要求通断，2要求断电
	uint8_t relayPowerCtrlOld;			//1要求通断，2要求断电，特殊判断，相当于再执行一次断电或上电
	
	//因为L610偶尔无故无法联网，所以累加24小时后，重启L610
	//如果后台设置过则在凌晨2~4点随机时间重启，如果没有设置，则累加够24小时则重启
	uint32_t RebootL610Cnt;	//单位秒
	uint32_t requestRTCFromL610;		//请求时间

	uint8_t  sendMcuVersion;			//系统上电后延时上报MCU版本计时器
	uint8_t  relayPowerSt;				//平台主动下发控制时进行状态清0，当自动控制时置位1

	uint16_t uartPctime;				//与PC通信的DMA 定时寄存器，由于硬件原因导致数据误触发。系统上电后30min 内有效

	uint8_t dtc_state;					//清除 查询故障码状态 00 - 空闲中，01 - 清除故障码，02 - 查询故障码
}L610_typedef;

/**ETC模块数据处理结构体*/
#define ETC_RECV_MSG_LEN	( 128 )		//ETC接收数据的最大长度
typedef struct
{
	uint8_t state;						//接收数据的状态
	uint8_t len;						//接收数据的长度
	uint8_t data[ETC_RECV_MSG_LEN];		//接收数据的缓存空间
	uint8_t save[ETC_RECV_MSG_LEN];		//接收数据缓存数据空间
}etc_recv_msg_t;

/**安全密钥数据处理结构体*/
#define VEH_SEED_KEY_LEN	( 64 )		//安全密钥SEED,KEY数据长度
typedef struct
{
	uint8_t len;						//数据长度
	uint8_t data[VEH_SEED_KEY_LEN + 3];		//数据内容
}veh_seed_key_msg_t;


void initL610Var(void);
void L610Process(void);
void saveL610IrtDa(uint8_t da);
void L610SecInc(void);
void HeartBeat2L610(void);
uint32_t sendHeartBeat2L610(void);

uint32_t recv_L610_data(uint8_t* pdata, uint32_t len);
void formart_L610_uart_recv(uint8_t* pdata, uint32_t len);
uint32_t parse_L610_uart_data(uint8_t* pdata, uint32_t len);
uint32_t get_para_car_id(uint8_t * ret_id);
uint32_t fill_serial_num(uint8_t * num);
uint32_t send_general_answer_to_L610(uint32_t cmd, uint32_t serial_num, uint8_t sta);
uint32_t uart_send_to_L610(uint8_t* pdata, uint32_t len);
uint32_t format_and_send_to_mcu(uint8_t * pdata, uint32_t len);
void clearRebootL610Sec(void);
uint32_t sendGDVersion2L610(void);
void rebootL610(void);
uint32_t send_utc_to_L610(void);

uint32_t send_general_answer_to_PC(uint32_t cmd, uint32_t serial_num, uint8_t sta);
uint32_t format_and_send_to_PC(uint8_t * pdata, uint32_t len);
uint32_t uart_send_to_PC(uint8_t* pdata, uint32_t len);
uint32_t format_and_send_to_uart(uint8_t * pdata, uint32_t len, uint8_t sel);
uint32_t send_general_package_to_uart(uint32_t cmd, uint8_t * pDa, uint32_t len, uint32_t serial_num, uint8_t serialUse, uint8_t sel);
uint32_t PCReadParaTable(void);
uint32_t uartWriteFlash(uint32_t adr, uint32_t len, uint8_t * pDa);
uint32_t uartReadFlash(uint32_t adr, uint32_t len);
uint32_t uartEraseFlash(uint32_t adr, uint32_t len);
uint32_t send2L610Alert(uint8_t type, uint32_t content);




uint32_t recv_PC_data(uint8_t* pdata, uint32_t len);


uint8_t getOnlyL610GeneralAnswer(void);
void clearOnlyL610GeneralAnswer(void);

//新增关于继电器控制相关
u8 saveRelay2Flash(u8 relayCtrl);
u8 readRelay2Flash(void);
u8 getCurrentRelayCtrlSta(void);
void judgeRelayPower(uint8_t ctrl);
	
uint32_t uartWriteFlash_CA(uint32_t len, uint8_t * pDa);
uint32_t uartReadFlash_CA(void);

void RebootL610CntPlus(void);
uint32_t getRandom_u32(void);
uint32_t request_rtc_from_L610(void);
void setRebootL610Time(uint8_t * rtcTime);

uint8_t saveSwSIMtoFlash(uint8_t sta);
uint8_t readSwSIMfromFlash(uint8_t *sta);

void rebootCANHardware(void);
void sendMcuVersion(void);
void sendMcuVersionToL610(void);
uint8_t rebootCANHardwareGet( void );
void RelayCtrlManage( void );
u8 saveRelayPowerFlash( u8 relayCtrl );

void etc_recv_msg_cache( uint8_t *buf, uint32_t len );
void etc_recv_msg_protocol_handle( void );
uint8_t etc_recv_msg_crc8( uint8_t *buffer, uint32_t bufSize );
void send_etc_msg_handle( uint8_t* pdata, uint32_t len );
uint8_t vehicle_key_save_to_flash( uint8_t *data, uint8_t len );
uint8_t vehicle_key_read_infor( uint8_t *infor );

#ifdef __cplusplus
}
#endif


#endif



